package com.lanyou.esb.cook.proxy.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.lanyou.esb.cook.proxy.common.Constants4Redis;
import com.lanyou.esb.cook.proxy.common.DateUtils;
import com.lanyou.esb.cook.proxy.entity.QuantityAnalysis;
import com.lanyou.esb.cook.proxy.exception.TimeIntervalException;
import com.lanyou.esb.cook.proxy.meta.TimeUnit;
import com.lanyou.esb.cook.proxy.redis.proxy.impl.QuantityAnalysisJedisProxy;
import com.lanyou.esb.cook.proxy.redis.vo.Group;
import com.lanyou.esb.cook.proxy.redis.vo.RedisActionType;
import com.lanyou.esb.cook.proxy.redis.vo.Group.Entry;
import com.lanyou.esb.cook.proxy.service.GroupService;
import com.lanyou.esb.cook.proxy.service.QuantityAnalysisService;

/**
 * 流量分析
 * 
 * @author Davey.wu
 */
public class QuantityAnalysisServiceImpl implements QuantityAnalysisService,
		GroupService<QuantityAnalysis> {
	/** 平台流量分析 **/
	private QuantityAnalysisJedisProxy quantityAnalysisJedisProxy;

	@Override
	public Group getGroup(QuantityAnalysis analysis) {
		if (analysis == null || analysis.getDate() == null
				|| StringUtils.isBlank(analysis.getResult())) {
			return null;
		}
		// 获取时间区间键值
		String timeSection = "";
		try {
			timeSection=getSection(analysis.getDate(), TimeUnit.SECOND,
					Constants4Redis.QUANTITY_ANALYSIS_INTERNAL_TIME);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		Group group = new Group();
		// string类型条件集合
		List<Entry> strs = new ArrayList<>(2);
		group.setStrs(strs);

		// 平台总流量
		Entry entry = new Entry();
		entry.setKey(quantityAnalysisJedisProxy.getKey(timeSection));
		entry.setValue(1 + "");
		entry.setTimeOut(quantityAnalysisJedisProxy.getTimeOut());
		entry.setType(RedisActionType.INCR_BY);
		strs.add(entry);

		// 成功（或者失败）
		entry = new Entry();
		entry.setKey(quantityAnalysisJedisProxy.generateSfKey(timeSection,
				analysis.getResult()));
		entry.setValue(1 + "");
		entry.setTimeOut(quantityAnalysisJedisProxy.getTimeOut());
		entry.setType(RedisActionType.INCR_BY);
		strs.add(entry);

		return group;
	}

	@Override
	public void pushToRedis(Date date, String result) {
		// 日期和调用结果不能为空
		if (date == null || StringUtils.isBlank(result)) {
			return;
		}
		try {
			// 获取时间区间键值
			String timeSection = getSection(date, TimeUnit.SECOND,
					Constants4Redis.QUANTITY_ANALYSIS_INTERNAL_TIME);
			// 平台流量+1,成功、失败次数+1
			quantityAnalysisJedisProxy.setex(timeSection, result, 1l);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TimeIntervalException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 获取时间区间
	 * 
	 * @param date
	 *            :时间
	 * @param timeUnit
	 *            ：时间单位
	 * @param interval
	 *            ：间隔
	 * @return
	 * @throws TimeIntervalException
	 */
	private String getSection(Date date, TimeUnit timeUnit, int interval)
			throws TimeIntervalException {
		switch (timeUnit) {
		case SECOND:
			return section4Seconds(date, interval);
		case MINUTE:
			return section4Minute(date, interval);
		case HOUR:
			return section4Hour(date, interval);
		case MONTH:
			// TODO 暂时不会到达这个维度
			break;
		case YEAR:
			// TODO 暂时不会到达这个维度
			break;
		default:
			return "";
		}
		return "";
	}

	/**
	 * 以小时为单位，划分时间区间<br>
	 * 描述：时间间隔应该是24的公因数
	 * 
	 * @param date
	 *            :日期
	 * @param interval
	 *            ：时间间隔
	 * @return
	 * @throws TimeIntervalException
	 */
	private String section4Hour(Date date, int interval)
			throws TimeIntervalException {
		// 不是24的公因数，视为无效时间间隔
		if (24 % interval != 0) {
			throw new TimeIntervalException("以小时为时间间隔单位时，时间间隔应该为24的公因数", "0");
		}

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// 计算秒所在区间的起始位置
		calendar.add(Calendar.HOUR_OF_DAY,
				-(calendar.get(Calendar.HOUR_OF_DAY) % interval));

		return DateUtils.DATEPATTERN_YYYYMMDDHHMM.format(calendar.getTime());
	}

	/**
	 * 以分钟为单位，划分时间区间<br>
	 * 描述：时间间隔应该是60的公因数
	 * 
	 * @param date
	 *            :日期
	 * @param interval
	 *            ：时间间隔
	 * @return
	 */
	private String section4Minute(Date date, int interval)
			throws TimeIntervalException {
		// 不是60的公因数，视为无效时间间隔
		if (60 % interval != 0) {
			throw new TimeIntervalException("以分钟为时间间隔单位时，时间间隔应该为60的公因数", "0");
		}

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// 计算秒所在区间的起始位置
		calendar.add(Calendar.MINUTE,
				-(calendar.get(Calendar.MINUTE) % interval));

		return DateUtils.DATEPATTERN_YYYYMMDDHHMM.format(calendar.getTime());
	}

	/**
	 * 以秒为单位，划分时间区间<br>
	 * 描述：时间间隔应该是60的公因数
	 * 
	 * @param date
	 *            :日期
	 * @param interval
	 *            ：时间间隔
	 * @return
	 */
	private String section4Seconds(Date date, int interval)
			throws TimeIntervalException {
		// 不是60的公因数，视为无效时间间隔
		if (60 % interval != 0) {
			throw new TimeIntervalException("以秒为时间间隔单位时，时间间隔应该为60的公因数", "0");
		}

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// 计算秒所在区间的起始位置
		calendar.add(Calendar.SECOND,
				-(calendar.get(Calendar.SECOND) % interval));

		return DateUtils.DATEPATTERN_YYYYMMDDHHMMSS.format(calendar.getTime());
	}

	public QuantityAnalysisJedisProxy getQuantityAnalysisJedisProxy() {
		return quantityAnalysisJedisProxy;
	}

	public void setQuantityAnalysisJedisProxy(
			QuantityAnalysisJedisProxy quantityAnalysisJedisProxy) {
		this.quantityAnalysisJedisProxy = quantityAnalysisJedisProxy;
	}

}
